package com.lancoo.rxretrofitlibrary.subscribers;

import android.content.Context;
import android.content.DialogInterface;
import android.net.ParseException;
import android.util.Log;

import com.afollestad.materialdialogs.MaterialDialog;
import com.google.gson.JsonIOException;
import com.google.gson.JsonParseException;
import com.lancoo.cpbase.authentication.base.CurrentUser;
import com.lancoo.cpbase.authentication.base.ExitBack;
import com.lancoo.cpbase.authentication.base.LoginBack;
import com.lancoo.cpbase.authentication.base.LoginOperate;
import com.lancoo.reviewsystem.utils.ToastUtils;
import com.lancoo.rxretrofitlibrary.Api.BaseApi;
import com.lancoo.rxretrofitlibrary.Api.UserInfo;
import com.lancoo.rxretrofitlibrary.R;
import com.lancoo.rxretrofitlibrary.RxRetrofitApp;
import com.lancoo.rxretrofitlibrary.exception.HttpTimeException;
import com.lancoo.rxretrofitlibrary.http.cookie.CookieResult;
import com.lancoo.rxretrofitlibrary.listener.HttpOnNextListener;
import com.lancoo.rxretrofitlibrary.utils.AppUtil;
import com.lancoo.rxretrofitlibrary.utils.CookieDbUtil;
import com.orhanobut.logger.Logger;
import com.trello.rxlifecycle.components.support.RxAppCompatActivity;

import org.json.JSONException;

import java.lang.ref.SoftReference;
import java.net.ConnectException;
import java.net.SocketTimeoutException;
import java.util.Random;

import rx.Observable;
import rx.Subscriber;

/**
 * 用于在Http请求开始时，自动显示一个ProgressDialog
 * 在Http请求结束是，关闭ProgressDialog
 * 调用者自己对请求数据进行处理
 * Created by tangminglong on 17/5/11.
 */

public class ProgressSubscriber<T> extends Subscriber<T> {


    /*是否弹框*/
    private boolean showProgress = true;
    /* 软引用回调接口*/
    private HttpOnNextListener mSubscriberOnNextListener;
    /*软引用反正内存泄露*/
    private SoftReference<RxAppCompatActivity> mActivity;
    /*加载框可自己定义*/
    //private ProgressDialog pd;
    private MaterialDialog materialDialog;

    /*请求数据*/
    private BaseApi api;



    /**
     * 构造
     *
     * @param api
     */
    public ProgressSubscriber(BaseApi api) {
        this.api = api;
        this.mSubscriberOnNextListener = api.getListener();
        this.mActivity = new SoftReference<>(api.getRxAppCompatActivity());
        setShowProgress(api.isShowProgress());
        if (api.isShowProgress()) {
            initProgressDialog();
        }
    }






    /**
     * 初始化加载框
     */
    private void initProgressDialog() {
        Context context = mActivity.get();
        if (materialDialog == null && context != null){

            materialDialog = new MaterialDialog.Builder(context)
                    .title(api.getProgressTitle())
                    .content(api.getProgressContent())
                    .progress(true,0)
                    .widgetColorRes(R.color.colorPrimary)
                    .cancelable(false)
                    .show();
            if (api.isCancel()){
                materialDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
                    @Override
                    public void onCancel(DialogInterface dialog) {
                        if (mSubscriberOnNextListener != null) {
                            mSubscriberOnNextListener.onCancel();
                        }
                        onCancelProgress();
                    }
                });
            }
        }


    }


    /**
     * 显示加载框
     */
    private void showProgressDialog() {
        if (!isShowProgress()) return;
        Context context = mActivity.get();
        if (materialDialog == null || context == null) return;
        if (materialDialog.isShowing()) {
            materialDialog.show();
        }
    }


    /**
     * 隐藏
     */
    private void dismissProgressDialog() {
        if (!isShowProgress()) return;
        if (materialDialog != null && materialDialog.isShowing()) {
            materialDialog.dismiss();
        }
    }


    /**
     * 订阅开始时调用
     * 显示ProgressDialog
     */
    @Override
    public void onStart() {
        showProgressDialog();
        /*缓存并且有网*/
        if (api.isCache() && AppUtil.isNetworkAvailable(RxRetrofitApp.getApplication())) {
           /*获取缓存数据*/
            CookieResult cookieResult = CookieDbUtil.getInstance().queryCookieBy(api.getUrl());
            if (cookieResult != null){
                long time = (System.currentTimeMillis() - cookieResult.getTime()) / 1000;
                if (time < api.getCookieNetWorkTime()){
                    if (mSubscriberOnNextListener != null){
                        mSubscriberOnNextListener.onCacheNext(cookieResult.getResult());
                    }
                    onCompleted();
                    unsubscribe();
                }
            }
        }
    }


    /**
     * 将onNext方法中的返回结果交给Activity或Fragment自己处理
     *
     * @param t 创建Subscriber时的泛型类型
     */
    @Override
    public void onNext(T t) {
        if (mSubscriberOnNextListener != null) {
            mSubscriberOnNextListener.onNext(t);
        }

    }

    /**
     * 完成，隐藏ProgressDialog
     */
    @Override
    public void onCompleted() {
        if (mSubscriberOnNextListener != null){
            mSubscriberOnNextListener.onComplete();
        }
        dismissProgressDialog();
    }

    /**
     * 对错误进行统一处理
     * 隐藏ProgressDialog
     *
     * @param e
     */
    @Override
    public void onError(Throwable e) {
        dismissProgressDialog();
        /*需要緩存并且本地有缓存才返回*/
        if (api.isCache()) {
            Observable.just(api.getUrl()).subscribe(new Subscriber<String>() {
                @Override
                public void onCompleted() {

                }

                @Override
                public void onError(Throwable e) {
                    errorDo(e);
                }

                @Override
                public void onNext(String s) {
                    /*获取缓存数据*/
                   CookieResult cookieResult = CookieDbUtil.getInstance().queryCookieBy(s);
                    if (cookieResult == null){
                        throw new HttpTimeException("网络错误");
                    }
                    long time = (System.currentTimeMillis() - cookieResult.getTime()) / 1000;
                    if (time < api.getCookieNoNetWorkTime()){
                        if (mSubscriberOnNextListener != null){
                            mSubscriberOnNextListener.onCacheNext(cookieResult.getResult());;
                        }
                    }else {
                        CookieDbUtil.getInstance().deleteCookie(cookieResult);
                        throw new HttpTimeException("网络错误");
                    }
                }
            });
        } else {
            errorDo(e);
        }
    }

    /*错误统一处理*/
    private void errorDo(Throwable e) {
        final Context context = mActivity.get();
        if (context == null) return;
        if (e instanceof SocketTimeoutException) {
            ToastUtils.showShort("网络中断，请检查您的网络状态");
        } else if (e instanceof ConnectException) {
            ToastUtils.showShort("网络中断，请检查您的网络状态");
        } else if (e instanceof JsonParseException || e instanceof ParseException ||
                e instanceof JSONException){
            ToastUtils.showShort("数据解析错误");
        }else {

            if ("Token失效".equals(e.getMessage())){
                LoginOperate mOperate = new LoginOperate(api.getRxAppCompatActivity());
                mOperate.openLoginDialog(new LoginBack() {
                    @Override
                    public void loginSuccess() {
                       UserInfo.Token = CurrentUser.Token;
                        ToastUtils.showShort("重新登录成功！");
                    }
                }, false, false, new ExitBack() {
                    @Override
                    public void exit() {

                    }
                });
            }else {
                e.printStackTrace();//在此打印错误的堆栈信息
                Logger.e("onNext执行错误  错误信息："+e);
                if (RxRetrofitApp.isDebug()) {
                    ToastUtils.showLong("错误" + e.getMessage());
                }
            }
        }
        if (mSubscriberOnNextListener != null) {
            mSubscriberOnNextListener.onError(e);
        }
    }



    /**
     * 取消ProgressDialog的时候，取消对observable的订阅，同时也取消了http请求
     */
    public void onCancelProgress() {
        if (!this.isUnsubscribed()) {
            this.unsubscribe();
        }
    }


    public boolean isShowProgress() {
        return showProgress;
    }

    /**
     * 是否需要弹框设置
     *
     * @param showProgress
     */
    public void setShowProgress(boolean showProgress) {
        this.showProgress = showProgress;
    }
}
